<?php
/**
 * This is LilForm helper. 
 *
 * @copyright     Copyright 2008-2010, LilCake.net
 * @link          http://lilcake.net LilCake.net
 * @package       lil
 * @subpackage    lil.views.helpers
 * @license       MIT License (http://www.opensource.org/licenses/mit-license.php)
 */
/**
 * LilFormHelper class
 *
 * @uses          Helper
 * @package       lil
 * @subpackage    lil.views.helpers
 */
class LilFormHelper extends AppHelper {
/**
 * helpers property
 *
 * @var array
 * @access public
 */
	var $helpers = array('Form', 'LilFloat.LilFloat', 'Lil.Lil');
/**
 * __call method
 *
 * @param mixed $method
 * @param mixed $params
 * @access private
 * @return void
 */
	function __call($method, $params) {
		if (!empty($params[0])) {
			if (is_callable(array($this->Form, $method))) {
				return (call_user_func_array(array($this->Form, $method), $params));
			}
		}
		return false;
	}
	
/**
 * Generates a form input element complete with label and wrapper div
 *
 * @param string $fieldName This should be "Modelname.fieldname"
 * @param array $options Each type of input takes different options.
 * @return string Completed form widget.
 * @access public
 * @link http://book.cakephp.org/view/1390/Automagic-Form-Elements
 */
	public function input($fieldName, $options = array()) {
		$default_options = array(
			'div' => array(
				'class' => array('ui-widget', 'ui-' . (isset($options['type']) ? $options['type'] : 'input')))
		);
		if (isset($options['div'])) {
			if (is_string($options['div'])) {
				$options['div'] = array('class' => explode(' ', $options['div']));;
			}
			if (isset($options['div']['class']) && is_string($options['div']['class'])) {
				$options['div']['class'] = explode(' ', $options['div']['class']);;
			}
			
			if ($options['div'] === false) {
				unset($default_options['div']);
			}
		}
		
		App::uses('LilDateEngine', 'Lil.Lib');
		$LilDate = LilDateEngine::getInstance();
		
		if (isset($options['type'])) {
			switch ($options['type']) {
				case 'time':
					if (!isset($options['timeFormat'])) $options['timeFormat'] = $LilDate->timeFormat();
					break;
		 		case 'date':
		 		case 'datetime':
		 			if (isset($default_options['div']))	$options['div']['class'][] = 'ui-text';
					if (!isset($options['size'])) $options['size'] = 10;
					
					$jsOptions = array();
					
					// UI datepicker format
					$dateFormat = implode($LilDate->dateSeparator(),
						str_split(strtr($LilDate->dateFormat(), array(
							'D' => 'dd', 'M' => 'mm', 'Y' => 'yy'
						)), 2)
					);
					$jsOptions['dateFormat'] = sprintf('"%s"', $dateFormat);
					
					// datepicker methods
					if (isset($options['onSelect'])) {
						$jsOptions['onSelect'] = $options['onSelect'];
						unset($options['onSelect']);
					}
					
					$jsImploded = '';
					foreach ($jsOptions as $jsK => $jsV) {
						if (!empty($jsImploded)) $jsImploded .= ', ';
						$jsImploded .= $jsK . ': ' . $jsV;
					}
					if (!empty($jsImploded)) $jsImploded = '{' . $jsImploded . '}';
					
					if ($dateValue = $this->Form->value($fieldName)) {
						if ($LilDate->isSql($dateValue)) {
							$dateFormat = str_split(strtr($LilDate->dateFormat(), array(
								'D' => '%d', 'M' => '%m', 'Y' => '%Y'
							)), 2);
							$options['value'] = strftime(
								implode($LilDate->dateSeparator(), $dateFormat),
								strtotime($dateValue)
							);
						}
					}
					
					if ($options['type'] == 'datetime') {
						$options['after'] = ' ' .
							$this->input($fieldName . '_time', array(
								'type'     => 'time',
								'div'      => false,
								'default'  => substr($this->Form->value($fieldName), 11),
								'label'    => false,
								'empty'    => isset($options['empty']) ? $options['empty'] : null,
								'interval' => isset($options['interval']) ? $options['interval'] : null
							)) . (isset($options['after'])?' ' . $options['after']:'');
					}
					$this->Lil->jsReady(
						sprintf(
						 	'$("#%1$s").datepicker(%2$s);',
						 	$this->Form->domId($fieldName),
						 	$jsImploded
						)
					);
					
					$options['type'] = 'text';
					break;
				case 'duration':
					$duration_secs = 0;
					if ($this->Form->value($fieldName . '_hours')) {
						$duration_secs = $this->Form->value($fieldName . '_hours') * 60 * 60;
						if ($this->Form->value($fieldName . '_minutes')) {
							$duration_secs += $this->Form->value($fieldName . '_minutes') * 60 * 60;
						}
					} else if ($this->Form->value($fieldName)) {
						$duration_secs = $this->Form->value($fieldName);
					} else if (!empty($options['default'])) {
						$duration_secs = $options['default'];
					}
					
					$days = floor($duration_secs / 3600 / 24);
					$minutes = (int)floor(($duration_secs % 3600) / 60);
					$hours = floor($duration_secs / 3600);
					
					$options['div']['class'][] = 'ui-duration';
					$options['type'] = 'text';
					$options['size'] = empty($options['size']) ? 2 : $options['size'];
					$options['value'] = $hours ? $hours : '';
					$options['after'] = ' ' . __dn('lil', 'hour', 'hours', $hours);
					
					$days_minutes_options = $options;
					
					if (isset($options['days']) && $options['days']) {
						$options['before'] = ' ' .
							$this->input($fieldName . '_days', array_merge($days_minutes_options, array(
								'type'    => 'text',
								'div'     => false,
								'label'   => false,
								'size'    => 2,
								'value'   => $days ? $days : '',
								'after'   => false
							))) . ' ' .
							(isset($options['separator']) ? $options['separator'] : __dn('lil', 'day', 'days', $days));
					}
					
					if (!isset($options['minutes']) || $options['minutes']) {
						$options['after'] .= ' ' .
							$this->input($fieldName . '_minutes', array_merge($days_minutes_options, array(
								'type'    => 'text',
								'div'     => false,
								'label'   => false,
								'size'    => 2,
								'value'   => $minutes ? $minutes : '',
								'after'   => false
							))) . ' ' .
							(isset($options['separator']) ? $options['separator'] : __dn('lil', 'minute', 'minutes', $minutes));
					}
					
					$fieldName .= '_hours';
					break;
				case 'money':
					$options['class'] = (isset($options['class'])?$options['class'].' ':'') . 'right';
					$options['value'] = $this->LilFloat->format(
						$this->Form->value($fieldName),
						isset($options['places']) ? $options['places'] : 2
					);
					$options['after'] = ' ' . $this->LilFloat->moneySymbol();
					
					$jsAvailableOptions = array('empty', 'places');
					// extract js options
					$jsExtracted = array_intersect_key($options, array_flip($jsAvailableOptions));
					// remove js options from field settings
					$options = array_diff_key($options, array_flip($jsAvailableOptions));
					
					// combine js options with defaults
					$jsDefaultOptions = array('empty' => true);
					$jsOptions = array_merge($jsDefaultOptions, $jsExtracted);
					$jsOptions['empty'] = $jsOptions['empty'] ? 'true' : 'false';
					
					$jsImploded = '';
					foreach ($jsOptions as $jsK => $jsV) {
						if (!empty($jsImploded)) $jsImploded .= ', ';
						$jsImploded .= $jsK . ': ' . $jsV;
					}
					if (!empty($jsImploded)) $jsImploded = '{' . $jsImploded . '}';
					
					$this->Lil->jsReady(
						sprintf(
						 	'$("#%1$s").LilFloat(%2$s);',
						 	$this->Form->domId($fieldName),
						 	$jsImploded
						)
					);
					
					break;
				case 'float':
				case 'decimal':
					$options['type'] = 'text';
					$options['class'] = (isset($options['class'])?$options['class'].' ':'') . 'right';
					$options['value'] = $this->LilFloat->format(
						$this->Form->value($fieldName),
						isset($options['places']) ? $options['places'] : 2
					);
					
					$jsAvailableOptions = array('empty', 'places');
					
					// extract js options
					$jsExtracted = array_intersect_key($options, array_flip($jsAvailableOptions));
					
					// remove js options from field settings
					$options = array_diff_key($options, array_flip($jsAvailableOptions));
					
					// combine js options with defaults
					$jsDefaultOptions = array('empty' => true);
					$jsOptions = array_merge($jsDefaultOptions, $jsExtracted);
					$jsOptions['empty'] = $jsOptions['empty'] ? 'true' : 'false';
					
					$jsImploded = '';
					foreach ($jsOptions as $jsK => $jsV) {
						if (!empty($jsImploded)) $jsImploded .= ', ';
						$jsImploded .= $jsK . ': ' . $jsV;
					}
					if (!empty($jsImploded)) $jsImploded = '{' . $jsImploded . '}';
					
					$this->Lil->jsReady(
						sprintf(
						 	'$("#%1$s").LilFloat(%2$s);',
						 	$this->Form->domId($fieldName),
						 	$jsImploded
						)
					);
					break;
			}
		}
		$new_options = array_merge_recursive($default_options, $options);
		
		if (is_array($new_options['div']['class'])) {
			$new_options['div']['class'] = implode(' ', $new_options['div']['class']);
		}
		
		return $this->Form->input($fieldName, $new_options);
	}
/**
 * Creates a submit button element.  This method will generate `<input />` elements that
 * can be used to submit, and reset forms by using $options.  image submits can be created by supplying an
 * image path for $caption.
 *
 * @param string $caption The label appearing on the button OR if string contains :// or the
 *  extension .jpg, .jpe, .jpeg, .gif, .png use an image if the extension
 *  exists, AND the first character is /, image is relative to webroot,
 *  OR if the first character is not /, image is relative to webroot/img.
 * @param array $options Array of options.  See above.
 * @return string A HTML submit button
 * @access public
 * @link http://book.cakephp.org/view/1431/submit
 */
	public function submit($caption = null, $options = array()) {
		$default_options = array(
		//'div' => array('class' => 'ui-widget ui-state-active'),
		);
		if (!isset($options['div'])) {
			return sprintf('<div class="ui-widget ui-submit">%s</div>',
				$this->Form->button($caption, array_merge($default_options, $options)));
		} else {
			return $this->Form->button($caption, array_merge($default_options, $options));
		}
	}
/**
 * Returns an HTML FORM element.
 *
 * @access public
 * @param string $model The model object which the form is being defined for
 * @param array $options An array of html attributes and options.
 * @return string An formatted opening FORM tag.
 * @link http://book.cakephp.org/view/1384/Creating-Forms
 */
	public function create($model = null, $options = array()) {
		return $this->Form->create($model, $options);
	}
/**
 * Closes an HTML form, cleans up values set by FormHelper::create(), and writes hidden
 * input fields where appropriate.
 *
 * @param mixed $options as a string will use $options as the value of button,
 * @return string a closing FORM tag optional submit button.
 * @access public
 * @link http://book.cakephp.org/view/1389/Closing-the-Form
 */
	public function end($options = null) {
		return $this->Form->end($options);
	}
}